/*
 * Copyright (C) 2005-2011 MaNGOS <http://www.getmangos.com/>
 *
 * Copyright (C) 2008-2011 Trinity <http://www.trinitycore.org/>
 *
 * Copyright (C) 2006-2011 ScriptDev2 <http://www.scriptdev2.com/>
 *
 * Copyright (C) 2010-2011 ProjectSkyfire <http://www.projectskyfire.org/>
 * 
 * Copyright (C) 2011 ArkCORE <http://www.arkania.net/>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 */

#include "ScriptPCH.h"
#include "naxxramas.h"

#define SAY_AGGRO           RAND(-1533109, -1533110, -1533111)
#define SAY_SLAY            -1533112
#define SAY_TAUNT           RAND(-1533113, -1533114, -1533115, -1533116, -1533117)
#define SAY_DEATH           -1533118

#define SPELL_SPELL_DISRUPTION  29310
#define SPELL_DECREPIT_FEVER    RAID_MODE(29998, 55011)
#define SPELL_PLAGUE_CLOUD      29350

enum Events {
	EVENT_NONE, EVENT_DISRUPT, EVENT_FEVER, EVENT_ERUPT, EVENT_PHASE,
};

enum Phases {
	PHASE_FIGHT = 1, PHASE_DANCE,
};

class boss_heigan: public CreatureScript {
public:
	boss_heigan() :
			CreatureScript("boss_heigan") {
	}

	CreatureAI* GetAI(Creature* pCreature) const {
		return new boss_heiganAI(pCreature);
	}

	struct boss_heiganAI: public BossAI {
		boss_heiganAI(Creature *c) :
				BossAI(c, BOSS_HEIGAN) {
			me->ApplySpellImmune(0, IMMUNITY_EFFECT, SPELL_EFFECT_KNOCK_BACK,
					true);
			me->ApplySpellImmune(0, IMMUNITY_MECHANIC, MECHANIC_GRIP, true);
		}

		uint32 eruptSection;
		bool eruptDirection;
		Phases phase;

		void KilledUnit(Unit* /*Victim*/) {
			if (!(rand() % 5))
				DoScriptText(SAY_SLAY, me);
		}

		void JustDied(Unit* /*Killer*/) {
			_JustDied();

			DoScriptText(SAY_DEATH, me);
		}

		void EnterCombat(Unit * /*who*/) {
			_EnterCombat();
			DoScriptText(SAY_AGGRO, me);
			EnterPhase(PHASE_FIGHT);
		}

		void EnterPhase(Phases newPhase) {
			phase = newPhase;
			events.Reset();
			eruptSection = 3;
			if (phase == PHASE_FIGHT) {
				events.ScheduleEvent(EVENT_DISRUPT, urand(10000, 25000));
				events.ScheduleEvent(EVENT_FEVER, urand(15000, 20000));
				events.ScheduleEvent(EVENT_PHASE, 90000);
				events.ScheduleEvent(EVENT_ERUPT, 15000);
			} else {
				float x, y, z, o;
				me->GetHomePosition(x, y, z, o);
				me->NearTeleportTo(x, y, z, o);
				DoCastAOE(SPELL_PLAGUE_CLOUD);
				events.ScheduleEvent(EVENT_PHASE, 45000);
				events.ScheduleEvent(EVENT_ERUPT, 8000);
			}
		}

		void UpdateAI(const uint32 diff) {
			if (!UpdateVictim() || !CheckInRoom())
				return;

			events.Update(diff);

			while (uint32 eventId = events.ExecuteEvent()) {
				switch (eventId) {
				case EVENT_DISRUPT:
					DoCastAOE(SPELL_SPELL_DISRUPTION);
					events.ScheduleEvent(EVENT_DISRUPT, urand(5000, 10000));
					break;
				case EVENT_FEVER:
					DoCastAOE(SPELL_DECREPIT_FEVER);
					events.ScheduleEvent(EVENT_FEVER, urand(20000, 25000));
					break;
				case EVENT_PHASE:
					// TODO : Add missing texts for both phase switches
					EnterPhase(
							phase == PHASE_FIGHT ? PHASE_DANCE : PHASE_FIGHT);
					break;
				case EVENT_ERUPT:
					instance->SetData(DATA_HEIGAN_ERUPT, eruptSection);
					TeleportCheaters();

					if (eruptSection == 0)
						eruptDirection = true;
					else if (eruptSection == 3)
						eruptDirection = false;

					eruptDirection ? ++eruptSection : --eruptSection;

					events.ScheduleEvent(EVENT_ERUPT,
							phase == PHASE_FIGHT ? 10000 : 3000);
					break;
				}
			}

			DoMeleeAttackIfReady();
		}
	};
};

void AddSC_boss_heigan() {
	new boss_heigan();
}
